﻿using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Globalization;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace WxSDK.Common
{
	/// <summary>
	/// 工具类
	/// </summary>
	public class WxUtility
	{
		private static Random rnd = new Random();

		/// <summary>
		/// 获得客户端IP
		/// </summary>
		/// <returns></returns>
		public static string GetClientIP()
		{
			string userIP;
			HttpRequest Request = HttpContext.Current.Request;
			// 如果使用代理，获取真实IP
			if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != "")
				userIP = Request.ServerVariables["REMOTE_ADDR"];
			else
				userIP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
			if (userIP == null || userIP == "")
				userIP = Request.UserHostAddress;
			return userIP;
		}

		/// <summary>
		/// 对输入的字符串进行MD5加密，返回小写形式
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static string MD5(string input)
		{
			using (MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider())
			{
				return BitConverter.ToString(provider.ComputeHash(Encoding.UTF8.GetBytes(input))).Replace("-", string.Empty).ToLower(CultureInfo.CurrentCulture);
			}
		}

		#region 随机字符串
		/// <summary>
		/// 生成一个指定长度的随机字符串a-Z0-9_*
		/// </summary>
		/// <param name="pwdlen">字符串长度</param>
		/// <returns>随机字符串</returns>
		public static string MakeRandomString(int pwdlen)
		{
			return MakeRandomString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_*", pwdlen);
		}
		/// <summary>
		/// 从一个指定的字符串中取出指定长度的随机字符串
		/// </summary>
		/// <param name="pwdchars">用于抽取随机字符串的字符串</param>
		/// <param name="pwdlen">生成的随机字符串长度</param>
		/// <returns>随机字符串</returns>
		public static string MakeRandomString(string pwdchars, int pwdlen)
		{
			StringBuilder builder = new StringBuilder();
			for (int i = 0; i < pwdlen; i++)
			{
				int num = rnd.Next(pwdchars.Length);
				builder.Append(pwdchars[num]);
			}
			return builder.ToString();
		}
		#endregion

		#region 时间戳
		/// <summary>
		/// 得到当前时间戳
		/// </summary>
		/// <param name="timeType">0：毫秒；1：秒；</param>
		/// <returns></returns>
		public static long CurrentTimeMillis(int timeType = 0)
		{
			long result = 0;
			var temp = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
			if (timeType == 0)
			{
				result = (long)temp.TotalMilliseconds;
			}
			else
			{
				result = (long)temp.TotalSeconds;
			}
			return result;
		}
		/// <summary>
		/// 时间戳转为C#格式时间
		/// </summary>
		/// <param name="timeStamp">Unix时间戳格式</param>
		/// <returns>C#格式时间</returns>
		public static DateTime GetTime(string timeStamp)
		{
			DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
			long lTime = long.Parse(timeStamp);
			if (timeStamp.Length == 13)
			{
				return dtStart.AddMilliseconds(lTime);
			}
			else if (timeStamp.Length == 10)
			{
				return dtStart.AddSeconds(lTime);
			}
			else
			{
				return dtStart.AddMilliseconds(lTime);
			}
		}
		#endregion

		#region 编码转换
		/// <summary>
		/// 对字符串进行Base64的解码
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static string Base64StringDecode(string input)
		{
			byte[] bytes = Convert.FromBase64String(input);
			return Encoding.UTF8.GetString(bytes);
		}
		/// <summary>
		/// 对字符串进行Base64的编码
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static string Base64StringEncode(string input)
		{
			return Convert.ToBase64String(Encoding.UTF8.GetBytes(input));
		}
		#endregion

		#region 安全转换到字符串
		/// <summary>
		/// 安全转换到字符串
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static string ToString(object input)
		{
			return ToString(input, "");
		}
		/// <summary>
		/// 安全转换到字符串
		/// </summary>
		/// <param name="input"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static string ToString(object input, string defaultValue)
		{
			if (Convert.IsDBNull(input) || object.Equals(input, null) || string.IsNullOrEmpty(input.ToString()))
			{
				return defaultValue;
			}
			return input.ToString();
		}
		#endregion

		#region AES解密
		/// <summary>
		/// AES解密。算法为 AES-128-CBC，数据采用PKCS#7填充。
		/// 主要用于微信小程序加密数据的解密使用。
		/// </summary>
		/// <param name="AesKey"></param>
		/// <param name="AesIV"></param>
		/// <param name="data"></param>
		/// <returns></returns>
		public static string AESDecrypt(string AesKey, string AesIV, string data)
		{
			try
			{
				//16进制数据转换成byte
				byte[] encryptedData = Convert.FromBase64String(data);
				RijndaelManaged rijndaelCipher = new RijndaelManaged();
				rijndaelCipher.Key = Convert.FromBase64String(AesKey);
				rijndaelCipher.IV = Convert.FromBase64String(AesIV);
				rijndaelCipher.Mode = CipherMode.CBC;
				rijndaelCipher.Padding = PaddingMode.PKCS7;
				ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
				byte[] plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
				string result = Encoding.Default.GetString(plainText);
				return result;
			}
			catch (Exception)
			{
				return null;

			}
		}
		/// <summary>
		/// AES解密。算法为 AES-256-ECB，数据采用PKCS#7填充。
		/// 主要用于微信小程序申请退款返回的加密数据的解密使用。
		/// </summary>
		/// <param name="AesKey"></param>
		/// <param name="data"></param>
		/// <returns></returns>
		public static string AESDecrypt(string AesKey, string data)
		{
			try
			{
				byte[] encryptedData = Convert.FromBase64String(data);
				RijndaelManaged rijndaelCipher = new RijndaelManaged();
				rijndaelCipher.Key = Encoding.UTF8.GetBytes(AesKey);//Convert.FromBase64String(AesKey);
				rijndaelCipher.Mode = CipherMode.ECB;
				rijndaelCipher.Padding = PaddingMode.PKCS7;
				ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
				byte[] plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
				string result = Encoding.Default.GetString(plainText);
				return result;
			}
			catch (Exception)
			{
				return null;

			}
		}
		#endregion
	}
}
